package com.xyy.saas.payment.service.job.impl;

import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.adapter.ChannelSettingManager;
import com.xyy.saas.payment.dao.mapper.PrePayOrderMapper;
import com.xyy.saas.payment.dao.mapper.RefundOrderMapper;
import com.xyy.saas.payment.dao.model.*;
import com.xyy.saas.payment.enums.TradeTypeEnum;
import com.xyy.saas.payment.exception.PaymentException;
import com.xyy.saas.payment.pojo.vo.FBankPayRecordsVo;
import com.xyy.saas.payment.service.FbankPayRecordsService;
import com.xyy.saas.payment.service.PayResultOrderService;
import com.xyy.saas.payment.service.job.FBankSFTPManage;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.WxUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;

@Slf4j
@Component
public class DownloadTradeBillService {
    @Resource
    private FbankPayRecordsService fbankPayRecordsService;
    @Resource
    private PayResultOrderService payResultOrderService;
    @Resource
    private PrePayOrderMapper prePayOrderMapper;
    @Resource
    private RefundOrderMapper refundOrderMapper;
    @Autowired
    private ChannelSettingManager channelSettingManager;

    /**
     * 下载微信直连交易单
     * @param merchantNo
     * @param date
     * @throws PaymentException
     */
    public void download(String merchantNo, String date) {
        log.info("DownloadTradeBillService.download, merchantNo={}, date={}", merchantNo, date);
        WxSettings wxSettings = channelSettingManager.getWXSettingByMchId(merchantNo);
        WxUtil.WxCertEntity wxCert = WxUtil.buildWxCert(merchantNo, FBankSFTPManage.apiV3Key(merchantNo),
                FBankSFTPManage.serialNo(merchantNo), wxSettings.getPrivateKey());
        Map<String, String> header = new HashMap<>();
        header.put("Accept","application/json");
        header.put("Content-type", "application/json; charset=utf-8");
        header.put("Wechatpay-Serial", FBankSFTPManage.serialNo(merchantNo));

        try {
            String result =  wxCert.wxHttpGetRequest("https://api.mch.weixin.qq.com/v3/bill/tradebill?bill_type=ALL&bill_date=" + date, header);
            log.info("DownloadTradeBillService.download：{}", result);
            Map<String, String> map = JSONUtils.parse2Map(result, String.class, String.class);
            read(wxCert.wxHttpGetStreamRequest(map.get("download_url"), header, Boolean.FALSE));
        }
        catch(Exception ex) {
            log.error(ex.getMessage(), ex);
        }
    }

    /**
     * 读取数据
     * @param in
     */
    private void read(InputStream in) {
        BufferedReader br = null;

        try {
            if(in != null) {
                br = new BufferedReader(new InputStreamReader(in));
                String data = null;

                while ((data = br.readLine()) != null) {
                    if(Boolean.parseBoolean(ApolloUtil.getProperty("wx_pay_records_download_debug", "false"))) {
                        log.info("原始数据：{}", data);
                    }

                    FbankPayRecords fbankPayRecords = FBankPayRecordsVo.parse3(data);

                    if(fbankPayRecords == null) {
                        log.error("ChannelSftpService#download data parse error, data={}", data);
                        continue;
                    }

                    if(!FBankPayRecordsVo.PAY_WX_MINI.equals(fbankPayRecords.getTradeType()) &&
                            !FBankPayRecordsVo.PAY_WX_PUB.equals(fbankPayRecords.getTradeType()) &&
                            !FBankPayRecordsVo.PAY_ALI.equals(fbankPayRecords.getTradeType()) &&
                            !FBankPayRecordsVo.REFUND.equals(fbankPayRecords.getTradeType()))
                    {
                        log.error("ChannelSftpService#download ignore trade type, data={}", data);
                        continue;
                    }

                    // 校验交易记录是否存在
                    if(fbankPayRecordsService.queryByOrderNo(fbankPayRecords.getOrderNo()) != null) {
                        continue;
                    }

                    fillParams(fbankPayRecords);

                    if(Boolean.parseBoolean(ApolloUtil.getProperty("wx_pay_records_download_debug", "false"))) {
                        log.info("入库数据：{}", JSONUtils.toJSON(fbankPayRecords));
                    }

                    fbankPayRecordsService.insertSelective(fbankPayRecords);
                }
            }
        }
        catch(Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        finally {
            if(br != null) {
                try {
                    br.close();
                }
                catch(Exception ex) {
                    log.error(ex.getMessage(), ex);
                }
            }
        }
    }

    private void fillParams(FbankPayRecords fbankPayRecords) {
        if(TradeTypeEnum.WXPAY.getCode().equals(fbankPayRecords.getTradeType())) {
            List<PayResultOrder> payResultOrders = payResultOrderService.selectListByPayNo(fbankPayRecords.getClientSerialNo());

            if(CollectionUtils.isEmpty(payResultOrders)) {
                log.error("DownloadTradeBillService#download Business Order not fount error(pay), data={}", JSONObject.toJSONString(fbankPayRecords));
                return;
            }

            PrePayOrder prePayOrder = prePayOrderMapper.getPrePayOrderByPayNo(fbankPayRecords.getClientSerialNo());
            fbankPayRecords.setBusinessType(prePayOrder.getBusinessType());
            // fbankPayRecords.setBusinessOrderType(prePayOrder.getBusinessOrderType());
            fbankPayRecords.setBusinessOrderType(fbankPayRecords.getMerchantNo());
            fbankPayRecords.setExtra(prePayOrder.getBusinessOrderNo());
            fbankPayRecords.setRemarks("直连微信支付");
        }
        else {
            RefundOrder refundOrder = refundOrderMapper.selectByChannelRefundNo(fbankPayRecords.getOrderNo(), fbankPayRecords.getOrderNo());

            if(refundOrder == null) {
                log.error("DownloadTradeBillService#download Business Order not fount error(refund), data={}", JSONObject.toJSONString(fbankPayRecords));
                return;
            }

            fbankPayRecords.setBusinessType(refundOrder.getBusinessType());

            // PayAccount payAccount = payAccountService.getPayAccountByAccountId(refundOrder.getUserId());
            // fbankPayRecords.setBusinessOrderType(payAccount.getBusinessUserId());
            fbankPayRecords.setBusinessOrderType(fbankPayRecords.getMerchantNo());
            fbankPayRecords.setExtra(refundOrder.getBusinessRefundNo());
            fbankPayRecords.setRemarks("直连微信退款");
        }
    }
}
